
package messaging;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;

import log.Logger;

import node.NodeManager;

/**
 * This class is responsible for finding the hash corresponding to the given
 * hash key .This class will also find the optimal node to forward the
 * message when the given node has no direct connection to the 
 * destonation node.
 * 
 * @author Team 4
 * @version 05/08/2013
 * 
 */
public class MessageHashing
{
  /**
   * Stores all the neighbours of all the nodes in the ring.
   */
  private HashMap<Integer, ArrayList<Integer>> node_connections =
      new HashMap<Integer, ArrayList<Integer>>();
  /**
   * Constructor.
   */
  public MessageHashing(final HashMap<Integer, ArrayList<Integer>> conn)
  {
    this.node_connections = conn;
  }
  /**
   * This method will find the hash key corresponding to the given string.
   * 
   * @param the_word - the message
   * @return the hash of the message
   */
  public static int findHashValue(final String the_word)
  {
    int hash_value = the_word.hashCode();
    if (hash_value < 0)
    {
      hash_value = hash_value * -1;
    }
    hash_value = hash_value % NodeManager.total_nodes_chord; 
    return hash_value;
  }

  /**
   * This method will find the optimum node number to forward the request if
   * none of the nodes connections handle this message.
   * 
   * @param my_node_num : stores the node number
   * @param final_dest : the final destination for this message.
   * @return int - the optimum node number it has to forward
   */
  public int optimalNodeFind(final int my_node_num, final int final_dest)
  {
    ArrayList<Integer> connec = new ArrayList<Integer>();
    connec = this.node_connections.get(my_node_num);
    Iterator itr = connec.iterator();
    int first_node = Collections.max(connec);
    int node;
    if (connec.contains(final_dest))
    {
      return final_dest;
    }
    else
    {
      if (itr.hasNext())
      {
        first_node = (int) itr.next();
      }
      while (itr.hasNext())
      {
        node = (int) itr.next();
        if (node > first_node  && final_dest > node)
        {
          first_node = node;
        }        
      }
      return first_node;
    }
  }
}
